﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GalaSoft.MvvmLight;
using EngineAdmin;
using GameEngine;
using DaphneProfiBase;
using Tomers.WPF.Localization;
using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Command;
using System.Windows;
using Microsoft.Win32;

namespace DaphneForms.ViewModel
{
    /// <summary>
    /// ViewModel for CB Engine Management Form
    /// </summary>
    public class CheckersBoardManageFormVM: ViewModelBase
    {

        private EngineRecord _selectedUnloadedEngine = null;

        /// <summary>
        /// Constructor
        /// </summary>
        public CheckersBoardManageFormVM()
        {
            LoadedEngines = new List<EngineRecord>();
            UnloadedEngines = new List<EngineRecord>();

            // bind the commands
            InstallEngineCommand = new RelayCommand(() => InstallEngine());
            RemoveEngineCommand = new RelayCommand(() => RemoveEngine());
            EngineOptionsCommand = new RelayCommand(() => EngineOptions());
            CloseCommand = new RelayCommand(() => CloseForm());
            LoadEngineCommand = new RelayCommand(() => LoadEngine());
            UnloadEngineCommand = new RelayCommand(() => UnloadEngine());

            // fill in engine datagrids
            PrepareEngineLists();
        }

        #region Binding Properties

        public List<EngineRecord> LoadedEngines
        { get; set; }

        public List<EngineRecord> UnloadedEngines
        { get; set; }

        public EngineRecord SelectedLoadedEngine
        { get; set; }

        public EngineRecord SelectedUnloadedEngine
        {
            get
            {
                return _selectedUnloadedEngine;
            }
            set
            {
                _selectedUnloadedEngine = value;
                UpdateEnginePath();
            }
        }

        public string EnginePath
        { get; set; }

        public RelayCommand InstallEngineCommand
        { get; set; }

        public RelayCommand RemoveEngineCommand
        { get; set; }

        public RelayCommand EngineOptionsCommand
        { get; set; }

        public RelayCommand LoadEngineCommand
        { get; set; }

        public RelayCommand UnloadEngineCommand
        { get; set; }

        public RelayCommand CloseCommand
        { get; set; }

        #endregion

        /// <summary>
        /// Command Handler for loading the installed engine
        /// </summary>
        private void LoadEngine()
        {
            if (SelectedUnloadedEngine == null)
                return;

            // get and load the engine
            var engine = SelectedUnloadedEngine.Engine;
            CBEngineManager.Instance().LoadEngine(engine);

            // refresh datagrids
            PrepareEngineLists();
        }

        /// <summary>
        /// Command Handler for unloading the selected engine
        /// </summary>
        private void UnloadEngine()
        {
            if (SelectedLoadedEngine == null)
                return;

            // get and unload the selected engine
            var engine = SelectedLoadedEngine.Engine;
            CBEngineManager.Instance().UnloadEngine(engine);

            // refresh datagrids
            PrepareEngineLists();
        }

        /// <summary>
        /// Sends the message to close the form
        /// </summary>
        private void CloseForm()
        {
            Messenger.Default.Send<NotificationMessage>(new NotificationMessage(this, Notify.CloseForm));
        }

        /// <summary>
        /// Command Handler for installing a new engine
        /// </summary>
        private void InstallEngine()
        {
            // run open file dialog
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.DefaultExt = ".dll";
            dlg.Filter = LanguageContext.Instance.Dictionary.Translate<string>("CheckersBoardFilter", "Value");
            dlg.CheckFileExists = true;
            dlg.CheckPathExists = true;
            if (dlg.ShowDialog() == true)
            {
                var engine = CBEngineManager.Instance().InstallEngine(dlg.FileName);
                if (engine == null)
                {
                    MessageBox.Show(CBEngineManager.Instance().ErrorMessage);
                }
                else
                {
                    // do refresh
                    PrepareEngineLists();
                }
            }
        }

        /// <summary>
        /// Command Handler for removing the existing installed engine
        /// </summary>
        private void RemoveEngine()
        {
            if (_selectedUnloadedEngine == null)
                return;

            if (MessageBox.Show(LanguageContext.Instance.Dictionary.Translate<string>("DeleteEngine", "Value"),
                string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                CBEngineManager.Instance().RemoveEngine(_selectedUnloadedEngine.Engine);
                PrepareEngineLists();
            }
        }

        /// <summary>
        /// Runs the engine options form
        /// </summary>
        private void EngineOptions()
        {
            MessageBox.Show("Not yet implemented.");
        }

        /// <summary>
        /// Update engine path
        /// </summary>
        private void UpdateEnginePath()
        {
            if (_selectedUnloadedEngine == null)
                return;

            EnginePath = _selectedUnloadedEngine.Engine.EnginePath;

            RaisePropertyChanged("EnginePath");
        }

        /// <summary>
        /// Prepares the engine lists
        /// </summary>
        private void PrepareEngineLists()
        {
            // clean up
            LoadedEngines.Clear();
            UnloadedEngines.Clear();

            // Prepare the list of loaded engines
            var loadedEngines = CBEngineManager.Instance().GetListOfLoadedEngines();
            foreach (var engine in loadedEngines)
            {
                EngineRecord rec = new EngineRecord();
                rec.Name = engine.GetEngineName();

                // resolve draughts type
                enumGameType? gameType = engine.GetDraughtsType();
                if (gameType.HasValue)
                {
                    var type = SupportedCheckers.Types.FirstOrDefault(i => i.CheckersType == gameType.Value);
                    if (type != null)
                    {
                        rec.Type = LanguageContext.Instance.Dictionary.Translate<string>(type.CheckersNameKey, "Value");                                                                      
                    }                 
                }

                rec.Engine = engine;
                LoadedEngines.Add(rec);
            }

            // Prepare the list of unloaded engines
            var unloadedEngines = CBEngineManager.Instance().GetListOfUnloadedEngines();
            foreach (var engine in unloadedEngines)
            {
                EngineRecord rec = new EngineRecord();
                rec.Name = engine.GetEngineName();

                // resolve draughts type
                enumGameType? gameType = engine.GetDraughtsType();
                if (gameType.HasValue)
                {
                    var type = SupportedCheckers.Types.FirstOrDefault(i => i.CheckersType == gameType.Value);
                    if (type != null)
                    {
                        rec.Type = LanguageContext.Instance.Dictionary.Translate<string>(type.CheckersNameKey, "Value");
                    }
                }

                rec.Engine = engine;
                UnloadedEngines.Add(rec);
            }

            // refresh datagrids
            RaisePropertyChanged("LoadedEngines");
            RaisePropertyChanged("UnloadedEngines");

            // refresh columns in the datagrid
            Messenger.Default.Send<NotificationMessage>(new NotificationMessage(this, Notify.ResetDataGrid));
        }


        /// <summary>
        /// CB Engine Record Class
        /// </summary>
        public class EngineRecord
        {
            public string Name
            { get; set; }

            public string Type
            { get; set; }

            public CBEngineFacade Engine
            { get; set; }
        }        
    }
}
